home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Telnet 2.7b5 / source / tek / vgtek.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-01  |  34.2 KB  |  1,547 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    vgtek.c by Aaron Contorer 1987 for NCSA
  3.  *    bugfixes by Tim Krauskopf 1988 for NCSA
  4.  *    TEK4105 support by Dave Whittington 1990 (for NCSA, of course)
  5.  *
  6.  *    Takes Tektronix codes as input; sends output to real graphics devices.
  7.  *
  8.  *    CHANGES TO MAKE:
  9.  *    create a function to make sure a window is attached to a real window.
  10.  *      Calling program will call this whenever switching between active windows.
  11.  *    Pass virtual window number to RG driver so it can call back.
  12.  */
  13.  
  14. #ifdef MPW
  15. #pragma segment TEKMAIN
  16. #endif
  17.  
  18. #include "event.proto.h"
  19. #include "maclook.proto.h"
  20. #include "wind.h"
  21.  
  22. #include "vsdata.h"
  23. #include "vsinterf.proto.h"
  24.  
  25. #include "vgfont.h"
  26. #include "vgtek.proto.h"
  27. #include "rg0.proto.h"
  28. #include "rgmp.proto.h"
  29. #include "tekrgmac.proto.h"
  30. #include "tekdefs.h"    /* NCSA: sb - all defines are now here, for easy access */
  31. #include "tekstor.proto.h"
  32.  
  33. static RGLINK RG[TEK_DEVICE_MAX] = {
  34.     RGMnewwin,        RGMdevname,        RGMinit,        RGMgin,
  35.     RGMpencolor,    RGMclrscr,        RGMclose,        RGMpoint,
  36.     RGMdrawline,    RGMinfo,        RGMpagedone,    RGMdataline,
  37.     RGMcharmode,    RGMgmode,        RGMtmode,        RGMshowcur,
  38.     RGMlockcur,        RGMhidecur,        RGMbell,        RGMuncover,
  39.  
  40.     RGMPnewwin,        RGMPdevname,    RGMPinit,        RG0returnshort,
  41.     RGMPpencolor,    RG0returnshort,    RGMPclose,        RGMPpoint,
  42.     RGMPdrawline,    RGMPinfo,        RG0oneshort,    RGMPdataline,
  43.     RGMPcharmode,    RG0void,        RG0void,        RG0void,
  44.     RG0void,        RG0void,        RG0oneshort,    RG0oneshort
  45. };
  46.  
  47. extern WindRec *screens;
  48.  
  49. static fontnum(short vw, short n);
  50. static storexy(short vw, short x, short y);
  51. static joinup(short hi, short lo, short e);
  52. static newcoord(short vw);
  53. static linefeed(short vw);
  54. static clipvec(short vw, short xa, short ya, short xb, short yb);
  55. static    short    VGcheck(short dnum);
  56.  
  57. static struct VGWINTYPE *VGwin[MAXVG];  /* BYU - virtual window descriptors */
  58.  
  59. static char state[MAXVG],savstate[MAXVG];
  60.     /* save state in a parallel array for speed */
  61. static TEKSTOREP VGstore[MAXVG]; /* the store where data for this window is kept */
  62. static char storing[MAXVG]; /* are we currently saving data from this window */
  63. static short drawing[MAXVG]; /* redrawing or not? */
  64.  
  65. static short charxset[NUMSIZES] = {56,51,34,31,112,168};
  66. static short charyset[NUMSIZES] = {88,82,53,48,176,264};
  67.  
  68. /*******************************************************************/
  69.  
  70. void    TEKMAINunload(void) {}
  71.  
  72. short donothing(void)    /* BYU LSC */
  73. {
  74.     return 0;
  75. }
  76.  
  77. /*
  78.  *    Set font for window 'vw' to size 'n'.
  79.  *    Sizes are 0..3 in Tek 4014 standard.
  80.  *    Sizes 4 & 5 are used internally for Tek 4105 emulation.
  81.  */
  82. static fontnum(short vw, short n)
  83. {
  84.     if ((n < 0) || (n >= NUMSIZES)) return(-1);
  85.     VGwin[vw]->fontnum = n;
  86.     VGwin[vw]->charx = charxset[n];
  87.     VGwin[vw]->chary = charyset[n];
  88.     return(0);
  89. }
  90.  
  91.  
  92. static storexy(short vw, short x, short y)
  93. /* set graphics x and y position */
  94. {
  95.     VGwin[vw]->curx = x;
  96.     VGwin[vw]->cury = y;
  97. }
  98.  
  99.  
  100. static joinup(short hi, short lo, short e)
  101. /* returns the number represented by the 3 pieces */
  102. {
  103. #if 1
  104.     return (((hi & 31) << 7) | ((lo & 31) << 2) | (e & 3));
  105. #else
  106.     return (((hi /* & 31 */ ) << 7) | ((lo /* & 31 */ ) << 2) | (e /* & 3 */));
  107. #endif
  108. } /* end joinup() */
  109.  
  110.  
  111. static newcoord(short vw)
  112. /*
  113.  *    Replace x,y with nx,ny
  114.  */
  115. {
  116.     VGwin[vw]->hiy = VGwin[vw]->nhiy;
  117.     VGwin[vw]->hix = VGwin[vw]->nhix;
  118.     VGwin[vw]->loy = VGwin[vw]->nloy;
  119.     VGwin[vw]->lox = VGwin[vw]->nlox;
  120.     VGwin[vw]->ey  = VGwin[vw]->ney;
  121.     VGwin[vw]->ex  = VGwin[vw]->nex;
  122.  
  123.     VGwin[vw]->curx = joinup(VGwin[vw]->nhix,VGwin[vw]->nlox,VGwin[vw]->nex);
  124.     VGwin[vw]->cury = joinup(VGwin[vw]->nhiy,VGwin[vw]->nloy,VGwin[vw]->ney);
  125. }
  126.  
  127.  
  128. static linefeed(short vw) 
  129. /* 
  130.  *    Perform a linefeed & cr (CHARTALL units) in specified window.
  131.  */
  132. {
  133. /*    short y = joinup(VGwin[vw]->hiy,VGwin[vw]->loy,VGwin[vw]->ey);*/
  134.     short y = VGwin[vw]->cury;
  135.     short x;
  136.  
  137.     if (y > VGwin[vw]->chary) y -= VGwin[vw]->chary;
  138.     else
  139.     {
  140.         y = 3119 - VGwin[vw]->chary;
  141.         VGwin[vw]->textcol = 2048 - VGwin[vw]->textcol;
  142.     }
  143.     x = VGwin[vw]->textcol;
  144.     storexy(vw,x,y);
  145. }
  146.  
  147. /*
  148.  *    Draw a vector in vw's window from x0,y0 to x1,y1.
  149.  *    Zoom the vector to the current visible window,
  150.  *    and clip it before drawing it.
  151.  *    Uses Liang-Barsky algorithm from ACM Transactions on Graphics,
  152.  *        Vol. 3, No. 1, January 1984, p. 7.
  153.  *
  154.  *  Note: since QuickDraw on the Mac already handles clipping, we
  155.  *          will not do any processing here.
  156.  *  14may91dsw
  157.  *
  158.  */
  159. static clipvec(short vw, short xa, short ya, short xb, short yb)
  160. {
  161.     short    t,b,l,r;
  162.     struct VGWINTYPE *vp;
  163.     long    hscale, vscale;
  164.     
  165.     vp = VGwin[vw];        /* BYU mod */
  166.  
  167.     hscale = INXMAX / (long) vp->winwide;
  168.     vscale = INYMAX / (long) vp->wintall;
  169.     
  170.     t = vp->wintop;
  171.     b = vp->winbot;
  172.     l = vp->winleft;
  173.     r = vp->winright;
  174.  
  175.     (*RG[vp->RGdevice].drawline) (vp->RGnum,
  176.         (short) ((long)(xa - l) * INXMAX / (long) vp->winwide),
  177.         (short) ((long)(ya- b) * INYMAX / (long) vp->wintall),
  178.         (short) ((long)(xb - l) * INXMAX / (long) vp->winwide),
  179.         (short) ((long)(yb- b) * INYMAX / (long) vp->wintall)
  180.         );
  181. } /* end clipvec() */
  182.  
  183.  
  184. /*
  185.  *    Draw a stroked character at the current cursor location.
  186.  *    Uses simple 8-directional moving, 8-directional drawing.
  187.  *
  188.  *    Modified 17jul90dsw: TEK4105 character set added.
  189.  */
  190. short    drawc(short vw, short c) /* character to draw */
  191. {
  192.     short        x,y,savex,savey;
  193.     short        strokex,strokey;
  194.     short        n;                        /* number of times to perform command */
  195.     char    *pstroke;                /* pointer into stroke data */
  196.     short        hmag,vmag;
  197.     short        xdir,ydir;
  198.     short        height;
  199.  
  200.     xdir = 1;
  201.     ydir = 0;
  202.  
  203.     if (c == 10)
  204.     {
  205.         linefeed(vw);
  206.         return(0);
  207.     }
  208.  
  209.     if (c == 7)
  210.     {
  211.         (*RG[VGwin[vw]->RGdevice].bell) (VGwin[vw]->RGnum);
  212.         TEKunstore(VGstore[vw]);
  213.         return(0);
  214.     }
  215.  
  216.     savey = y = VGwin[vw]->cury;
  217.     savex = x = VGwin[vw]->curx;
  218.  
  219.     if (c == 8)
  220.     {
  221.         if (savex <= VGwin[vw]->textcol) return(0);
  222.         savex -= VGwin[vw]->charx;
  223.         if (savex < VGwin[vw]->textcol) savex = VGwin[vw]->textcol;
  224.         VGwin[vw]->cury = savey;
  225.         VGwin[vw]->curx = savex;
  226.         return(0);
  227.     }
  228.  
  229.     if (VGwin[vw]->TEKtype)
  230.     {
  231.         height = VGwin[vw]->TEKSize;
  232.         if (c > 126)
  233.         {
  234.             height = 1;
  235.             (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->pencolor);
  236.         }
  237.         else
  238.             (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->TEKIndex);
  239.         hmag = (height*8);
  240.         vmag = (height*8);
  241.         
  242.         xdir = 0;
  243.         switch(VGwin[vw]->TEKRot)
  244.         {
  245.             case 0:
  246.                 xdir = 1;
  247.                 break;
  248.             case 90:
  249.                 ydir = 1;
  250.                 break;
  251.             case 180:
  252.                 xdir = -1;
  253.                 break;
  254.             case 270:
  255.                 ydir = -1;
  256.                 break;
  257.         }
  258.     }
  259.     else
  260.     {
  261.         hmag = VGwin[vw]->charx / 10;
  262.         vmag = VGwin[vw]->chary / 10;
  263.     }
  264.  
  265.     if ((c < 32) || (c > 137))
  266.         return(0);                    // Is this return value correct?
  267.     c -= 32;
  268.     pstroke = (VGwin[vw]->TEKtype) ? VGTEKfont[c] : VGfont[c];
  269.     while (*pstroke)
  270.     {
  271.         strokex = x;
  272.         strokey = y;
  273.         n = (*(pstroke++) - 48);    /* run length */
  274.         c = *(pstroke++);            /* direction code */
  275.  
  276.         switch(c)     /* horizontal movement: positive = right */
  277.         {
  278.         case 'e': case 'd': case 'c': case 'y': case 'h': case 'n':
  279.             x += (n * hmag) * xdir;
  280.             y += (n * hmag) * ydir;
  281.             break;
  282.         case 'q': case 'a': case 'z': case 'r': case 'f': case 'v':
  283.             x -= (n * hmag) * xdir;
  284.             y -= (n * hmag) * ydir;
  285.         }
  286.  
  287.         switch(c)    /* vertical movement: positive = up */
  288.         {
  289.         case 'q': case 'w': case 'e': case 'r': case 't': case 'y':
  290.             x -= (n * vmag) * ydir;
  291.             y += (n * vmag) * xdir;
  292.             break;
  293.         case 'z': case 'x': case 'c': case 'v': case 'b': case 'n':
  294.             x += (n * vmag) * ydir;
  295.             y -= (n * vmag) * xdir;
  296.         }
  297.  
  298.         switch(c)    /* draw or move */
  299.         {
  300.         case 'r': case 't': case 'y': case 'f': case 'h':
  301.         case 'v': case 'b': case 'n':
  302.             clipvec (vw,strokex,strokey,x,y);
  303.             break;
  304.         }
  305.     
  306.     } /* end while not at end of string */
  307.  
  308.     /* Update cursor location to next char position */
  309.     savex += VGwin[vw]->charx * xdir;
  310.     savey += VGwin[vw]->charx * ydir;
  311.     if ((savex < 0) || (savex > 4095) || (savey < 0) || (savey > 3119))
  312.     {
  313.         savex = savex < 0 ? 0 : savex > 4095 ? 4095 : savex;
  314.         savey = savey < 0 ? 0 : savey > 3119 ? 3119 : savey;
  315.     }
  316.  
  317.     if (VGwin[vw]->TEKtype)
  318.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->pencolor);
  319.  
  320.     VGwin[vw]->cury = savey;
  321.     VGwin[vw]->curx = savex;
  322. }
  323.  
  324. /***********************************************************
  325. ************************************************************
  326. ***                                                         ***
  327. **    All routines given below may be called by the user      **
  328. **    program.  No routines given above may be called from  **
  329. **    the user program.                                      **
  330. ***                                                         ***
  331. ************************************************************
  332. ***********************************************************/
  333.  
  334. /*    Initialize the whole VG environment.  Should be called ONCE
  335.  *    at program startup before using the VG routines.
  336.  */
  337. void    VGinit(void)
  338. {
  339.     short i;
  340.  
  341.     for (i = 0; i < MAXVG; i++) {
  342.         VGwin[i] = nil;
  343.         }
  344.  
  345.     for (i=0; i<TEK_DEVICE_MAX; i++) (*RG[i].init)();        /* BYU LSC */
  346. }
  347.  
  348. short VGgetVS(short theVGnum)                /* NCSA 2.5: give us the VS */
  349. {                                            /* NCSA 2.5 */
  350.     if (VGcheck(theVGnum)) {
  351.         return -1;
  352.         }
  353.         
  354.     return VGwin[theVGnum]->theVS;            /* NCSA 2.5 */
  355. }                                            /* NCSA 2.5 */
  356.  
  357. static    short    VGcheck(short dnum)
  358. {
  359.     if ((dnum >= MAXVG) || (dnum < 0)) return -1;
  360.  
  361.     if (VGwin[dnum] == nil) return -1;
  362.  
  363.     return 0;
  364. }
  365.  
  366. /*
  367.  *    create a new VG window and return its number.
  368.  *    New window will be attached to specified real device.
  369.  *    Returns -1 if unable to create a new VG window.
  370.  *
  371.  *    Modified 16jul90dsw: Support selection of 4105 or 4014.
  372.  */
  373. short VGnewwin
  374.   (
  375.     short device, /* number of RG device to use */
  376.     short theVS
  377.   )
  378. {
  379.     short    vw = 0;
  380.     short    theScrn;
  381.  
  382.     while ((vw < MAXVG) && (VGwin[vw] != nil)) vw++;
  383.     if (vw == MAXVG)
  384.         return(-1);
  385.         
  386.     VGwin[vw] = (struct VGWINTYPE *) myNewPtr(sizeof(struct VGWINTYPE));
  387.     if (VGwin[vw] == nil) {
  388.         return -1;
  389.         }
  390.             
  391.     VGstore[vw] = newTEKstore();
  392.     if (VGstore[vw] == nil) {
  393.         DisposePtr((Ptr)VGwin[vw]);
  394.         VGwin[vw] = nil;
  395.         return -1;
  396.         }
  397.     
  398.     VGwin[vw]->id = 'VGWN';
  399.     VGwin[vw]->RGdevice = device;
  400.     VGwin[vw]->RGnum = (*RG[device].newwin)();
  401.  
  402.     theScrn = findbyVS(theVS);
  403.     VGwin[vw]->TEKtype = screens[theScrn].tektype;    // 0 = 4014, 1 = 4105
  404.  
  405.     if (VGwin[vw]->RGnum < 0)
  406.     {
  407.         /* no windows available on device */
  408.         DisposePtr((Ptr)VGwin[vw]);
  409.         VGwin[vw] = nil;
  410.         freeTEKstore(VGstore[vw]);
  411.         return(-1);
  412.     }
  413.             
  414.     VGwin[vw]->mode = ALPHA;
  415.     VGwin[vw]->TEKPanel = (pointlist) NULL;
  416.     VGwin[vw]->theVS = theVS;
  417.     state[vw] = DONE;
  418.     storing[vw] = TRUE;
  419.     VGwin[vw]->textcol = 0;
  420.     drawing[vw] = 1;
  421.     fontnum(vw,0);
  422.     (*RG[device].pencolor)(VGwin[vw]->RGnum,1);
  423.  
  424.     storexy(vw,0,3071);
  425. #if 1                                        /* BYU LSC */
  426.     VGzoom(vw,0,0,4095,3119);                /* BYU LSC - important */
  427. #else                                        /* BYU LSC */
  428.     VGzoom(vw,0,0,INXMAX-1,INYMAX-1);
  429. #endif                                        /* BYU LSC */
  430.     return(vw);
  431. }
  432.  
  433. /*    Release its real graphics device and its store. */
  434. void    VGclose(short vw)
  435. {
  436.     if (VGcheck(vw)) {
  437.         return;
  438.         }
  439.  
  440.     (*RG[VGwin[vw]->RGdevice].close)(VGwin[vw]->RGnum);
  441.     freeTEKstore(VGstore[vw]);
  442.     DisposePtr((Ptr)VGwin[vw]);
  443.     VGwin[vw] = nil;
  444. }
  445.  
  446. /*    Detach window from its current device and attach it to the
  447.  *    specified device.  Returns negative number if unable to do so.
  448.  *    Sample application:  switching an image from #9 to Hercules.
  449.  *    Must redraw after calling this.
  450.  */
  451. short    VGdevice(short vw, short dev)
  452. {
  453.     short newwin;
  454.  
  455.     if (VGcheck(vw)) {
  456.         return -1;
  457.         }
  458.  
  459.     newwin = (*RG[dev].newwin)();
  460.     if (newwin<0) return(newwin);    /* unable to open new window */
  461.  
  462.     (*RG[VGwin[vw]->RGdevice].close)(VGwin[vw]->RGnum);
  463.     VGwin[vw]->RGdevice = dev;
  464.     VGwin[vw]->RGnum = newwin;
  465.     VGwin[vw]->pencolor = 1;
  466.     VGwin[vw]->TEKBackground = 0;
  467.     fontnum(vw,1);
  468.     return(0);
  469. }
  470.  
  471. /*    Clear the store associated with window vw.  
  472.  *    All contents are lost.
  473.  *    User program can call this whenever desired.
  474.  *    Automatically called after receipt of Tek page command. */
  475. void    VGclrstor(short vw)
  476. {
  477.     if (VGcheck(vw)) {
  478.         return;
  479.         }
  480.  
  481.     freeTEKstore(VGstore[vw]);
  482.     VGstore[vw] = newTEKstore();
  483.         /* Don't have to check for errors --    */
  484.         /* there was definitely enough memory.    */
  485. }
  486.  
  487. /*    Successively call the function pointed to by 'func' for each
  488.  *    character stored from window vw.  Each character will
  489.  *    be passed in integer form as the only parameter.  A value of -1
  490.  *    will be passed on the last call to indicate the end of the data.
  491.  */
  492. void    VGdumpstore(short vw, short (*func )(short))
  493. {
  494.     short        data;
  495.     TEKSTOREP    st;
  496.  
  497.     if (VGcheck(vw)) {
  498.         return;
  499.         }
  500.  
  501.     st = VGstore[vw];
  502.     topTEKstore(st);
  503.     while ((data = nextTEKitem(st)) != -1) (*func)(data);
  504.     (*func)(-1);
  505. }
  506.  
  507. /*    This is the main Tek emulator process.  Pass it the window and
  508.  *    the latest input character, and it will take care of the rest.
  509.  *    Calls RG functions as well as local zoom and character drawing
  510.  *    functions.
  511.  *
  512.  *    Modified 16jul90dsw:
  513.  *        Added 4105 support.
  514.  */
  515. void VGdraw(short vw, char c)            /* the latest input char */
  516. {
  517.     char        cmd;
  518.     char        value;
  519.     char        goagain;    /* true means go thru the function a second time */
  520.     char        temp[80];
  521.     RgnHandle    PanelRgn;
  522.     struct    VGWINTYPE *vp;
  523.     pointlist    temppoint;
  524.  
  525.     if (VGcheck(vw)) {
  526.         return;
  527.         }
  528.  
  529.     vp = VGwin[vw];        /* BYU */
  530.  
  531.     temp[0] = c;
  532.     temp[1] = (char) 0;
  533.  
  534.     /*** MAIN LOOP ***/
  535.      do
  536.     {
  537.         c &= 0x7f;                /* BYU 2.4.15 */
  538.          cmd = (c >> 5) & 0x03;
  539.         value = c & 0x1f;
  540.         goagain = FALSE;
  541.  
  542.         switch(state[vw])
  543.         {
  544.         case HIY: /* beginning of a vector */
  545.             vp->nhiy = vp->hiy;
  546.             vp->nhix = vp->hix;
  547.             vp->nloy = vp->loy;
  548.             vp->nlox = vp->lox;
  549.             vp->ney  = vp->ey;
  550.             vp->nex  = vp->ex;
  551.             
  552.             switch(cmd)
  553.             {
  554.             case 0:
  555.                 if (value == 27)        /* escape sequence */
  556.                 {
  557.                     state[vw] = ESCOUT;
  558.                     savstate[vw] = HIY;
  559.                 }
  560.                 else if (value < 27)    /* ignore */
  561.                 {
  562.                     break;
  563.                 }
  564.                 else
  565.                 {
  566.                     state[vw] = CANCEL;
  567.                     goagain = TRUE;
  568.                 }
  569.                 break;
  570.             case 1:                        /* hiy */
  571.                 vp->nhiy = value;
  572.                 state[vw] = EXTRA;
  573.                 break;
  574.             case 2:                        /* lox */
  575.                 vp->nlox = value;
  576.                 state[vw] = DONE;
  577.                 break;
  578.             case 3:                        /* extra or loy */
  579.                 vp->nloy = value;
  580.                 state[vw] = LOY;
  581.                 break;
  582.             }
  583.             break;        
  584.         case ESCOUT:
  585.             if ((value != 13) && (value != 10) && (value != 27) && (value != '~'))
  586.             {
  587.                 state[vw] = savstate[vw];        /* skip all EOL-type characters */
  588.                 goagain = TRUE;
  589.             }
  590.             break;
  591.         case EXTRA:    /* got hiy; expecting extra or loy */
  592.             switch(cmd)
  593.             {
  594.             case 0:
  595.                 if (value == 27)        /* escape sequence */
  596.                 {
  597.                     state[vw] = ESCOUT;
  598.                     savstate[vw] = EXTRA;
  599.                 }
  600.                 else if (value < 27)    /* ignore */
  601.                 {
  602.                     break;
  603.                 }
  604.                 else
  605.                 {
  606.                     state[vw] = DONE;
  607.                     goagain = TRUE;
  608.                 }
  609.                 break;
  610.             case 1:                        /* hix */
  611.                 vp->nhix = value;
  612.                 state[vw] = LOX;
  613.                 break;
  614.             case 2:                        /* lox */
  615.                 vp->nlox = value;
  616.                 state[vw] = DONE;
  617.                 break;
  618.             case 3:                        /* extra or loy */
  619.                 vp->nloy = value;
  620.                 state[vw] = LOY;
  621.                 break;
  622.             }
  623.             break;
  624.         case LOY: /* got extra or loy; next may be loy or something else */
  625.             switch(cmd)
  626.             {
  627.             case 0:
  628.                 if (value == 27)        /* escape sequence */
  629.                 {
  630.                     state[vw] = ESCOUT;
  631.                     savstate[vw] = LOY;
  632.                 }
  633.                 else if (value < 27)    /* ignore */
  634.                 {
  635.                     break;
  636.                 }
  637.                 else
  638.                 {
  639.                     state[vw] = DONE;
  640.                     goagain = TRUE;
  641.                 }
  642.                 break;
  643.             case 1: /* hix */
  644.                 vp->nhix = value;
  645.                 state[vw] = LOX;
  646.                 break;
  647.             case 2: /* lox */
  648.                 vp->nlox = value;
  649.                 state[vw] = DONE;
  650.                 break;
  651.             case 3: /* this is loy; previous loy was really extra */
  652.                 vp->ney = (vp->nloy >> 2) & 3;
  653.                 vp->nex = vp->nloy & 3;
  654.                 vp->nloy = value;
  655.                 state[vw] = HIX;
  656.                 break;
  657.             }
  658.             break;
  659.         case HIX:                        /* hix or lox */
  660.             switch(cmd)
  661.             {
  662.             case 0:
  663.                 if (value == 27)        /* escape sequence */
  664.                 {
  665.                     state[vw] = ESCOUT;
  666.                     savstate[vw] = HIX;
  667.                 }
  668.                 else if (value < 27)    /* ignore */
  669.                 {
  670.                     break;
  671.                 }
  672.                 else
  673.                 {
  674.                     state[vw] = DONE;
  675.                     goagain = TRUE;
  676.                 }
  677.                 break;
  678.             case 1:                        /* hix */
  679.                 vp->nhix = value;
  680.                 state[vw] = LOX;
  681.                 break;
  682.             case 2:                        /* lox */
  683.                 vp->nlox = value;
  684.                 state[vw] = DONE;
  685.                 break;
  686.             }
  687.              break;
  688.     
  689.         case LOX:                        /* must be lox */
  690.             switch(cmd)
  691.             {
  692.             case 0:
  693.                 if (value == 27)        /* escape sequence */
  694.                 {
  695.                     state[vw] = ESCOUT;
  696.                     savstate[vw] = LOX;
  697.                 }
  698.                 else if (value < 27)    /* ignore */
  699.                 {
  700.                     break;
  701.                 }
  702.                 else
  703.                 {
  704.                     state[vw] = DONE;
  705.                     goagain = TRUE;
  706.                 }
  707.                 break;
  708.             case 2:
  709.                 vp->nlox = value;
  710.                 state[vw] = DONE;
  711.                 break;
  712.             }
  713.             break;
  714.     
  715.         case ENTERVEC:
  716.             if (c == 7) vp->mode = DRAW;
  717.             if (c < 32)
  718.             {
  719.                 state[vw] = DONE;
  720.                 goagain = TRUE;
  721.                 vp->mode = DONE;
  722.                 break;
  723.             }
  724.             state[vw] = HIY;
  725.             vp->mode = TEMPMOVE;
  726.             vp->modesave = DRAW;
  727.             goagain = TRUE;
  728.             break;
  729.         case RS:
  730.             switch (c)
  731.             {
  732.             case ' ':                /* pen up */
  733.                 vp->modesave = vp->mode;
  734.                 vp->mode = TEMPMOVE;
  735.                 break;
  736.             case 'P':                /* pen down */
  737.                 vp->mode = DRAW;
  738.                 break;
  739.             case 'D':                /* move up */
  740.                 vp->cury++;
  741.                 break;
  742.             case 'E':
  743.                 vp->cury++;
  744.                 vp->curx++;
  745.                 break;
  746.             case 'A':
  747.                 vp->curx++;
  748.                 break;
  749.             case 'I':
  750.                 vp->curx++;
  751.                 vp->cury--;
  752.                 break;
  753.             case 'H':
  754.                 vp->cury--;
  755.                 break;
  756.             case 'J':
  757.                 vp->curx--;
  758.                 vp->cury--;
  759.                 break;
  760.             case 'B':
  761.                 vp->curx--;
  762.                 break;
  763.             case 'F':
  764.                 vp->cury++;
  765.                 vp->curx--;
  766.                 break;
  767.             case 27:
  768.                 savstate[vw] = RS;
  769.                 state[vw] = ESCOUT;
  770.                 break;
  771.             default:
  772. /*                storexy(vw,vp->curx,vp->cury);*/
  773.                 state[vw] = CANCEL;
  774.                 goagain = TRUE;
  775.                 break;
  776.             }
  777.             if (vp->mode == DRAW)
  778.                 clipvec(vw,vp->curx,vp->cury,vp->curx,vp->cury);
  779.             break;
  780.         case CMD0: /* *->CMD0: get 1st letter of cmd */
  781.             switch(c)
  782.             {
  783.             case 29:                    /* GS, start draw */
  784.                 state[vw] = DONE;
  785.                 goagain = TRUE;
  786.                 break;
  787.             case '%':
  788.                 state[vw] = TERMSTAT;
  789.                 break;
  790.             case '8':
  791.                 fontnum(vw,0);
  792.                 state[vw] = DONE;
  793.                 break;
  794.             case '9':
  795.                 fontnum(vw,1);
  796.                 state[vw] = DONE;
  797.                 break;
  798.             case ':':
  799.                 fontnum(vw,2);
  800.                 state[vw] = DONE;
  801.                 break;
  802.             case ';':
  803.                 fontnum(vw,3);
  804.                 state[vw] = DONE;
  805.                 break;
  806.             case 12: /* form feed = clrscr */
  807.                 if (screens[findbyVS(vp->theVS)].tekclear) {
  808.                     VGpage(vw);
  809.                     VGclrstor(vw);
  810.                 }
  811.                 break;
  812.             case 'L':
  813.                 state[vw] = SOMEL;
  814.                 break;
  815.             case 'K':
  816.                 state[vw] = IGNORE;
  817.                 break;
  818.             case 'M':
  819.                 state[vw] = SOMEM;
  820.                 break;
  821.             case 'R':
  822.                 state[vw] = SOMER;
  823.                 break;
  824.             case 'T':
  825.                 state[vw] = SOMET;
  826.                 break;
  827.             case 26:
  828.                 (*RG[vp->RGdevice].gin)(vp->RGnum);
  829.                 TEKunstore(VGstore[vw]);
  830.                 TEKunstore(VGstore[vw]);
  831.                 break;
  832.             case 10:
  833.             case 13:
  834.             case 27:
  835.             case '~':
  836.                 savstate[vw] = DONE;
  837.                 state[vw] = ESCOUT;
  838.                 break;            /* completely ignore these after ESC */
  839.             default:
  840.                 state[vw] = DONE;
  841.             }
  842.             break;
  843.         case TERMSTAT:
  844.             switch(c)
  845.             {
  846.                 case '!':
  847.                     state[vw] = INTEGER;        /* Drop the next integer */
  848.                     savstate[vw] = DONE;
  849.                     break;
  850.             }
  851.             break;
  852.         case SOMER:
  853.             switch(c)
  854.             {
  855.                 case 'A':
  856.                     state[vw] = INTEGER;
  857.                     savstate[vw] = VIEWAT;
  858.                     break;
  859.                 default:
  860.                     state[vw] = DONE;
  861.             }
  862.             break;
  863.         case VIEWAT:
  864.             state[vw] = INTEGER;
  865.             savstate[vw] = VIEWAT2;
  866.             goagain = TRUE;
  867.             break;
  868.         case VIEWAT2:
  869.             vp->TEKBackground = vp->intin < 0 ? 0 : vp->intin > 7 ? 7 : vp->intin;
  870.             state[vw] = INTEGER;
  871.             savstate[vw] = DONE;
  872.             goagain = TRUE;
  873.             break;
  874.         case SOMET:                /* Got ESC T; now handle 3rd char. */
  875.             switch(c)
  876.             {
  877.             case 'C':            /* GCURSOR */
  878.                 vp->intin = 3;
  879.                 state[vw] = STARTDISC;
  880.                 break;
  881.             case 'D':
  882.                 vp->intin = 2;
  883.                 state[vw] = STARTDISC;
  884.                 break;
  885.             case 'F':            /* set dialog area color map */
  886.                 state[vw] = JUNKARRAY;
  887.                 break;
  888.             case 'G':            /* set surface color map */
  889.                 state[vw] = INTEGER;
  890.                 savstate[vw] = JUNKARRAY;
  891.                 break;
  892.             default:
  893.                 state[vw] = DONE;
  894.             }            
  895.             break;
  896.         case JUNKARRAY:            /* This character is the beginning of an integer
  897.                                     array to be discarded.  Get array size. */
  898.             savstate[vw] = STARTDISC;
  899.             state[vw] = INTEGER;
  900.             break;                    
  901.         case STARTDISC:            /* Begin discarding integers. */
  902.             vp->count = vp->intin + 1;
  903.             goagain = TRUE;
  904.             state[vw] = DISCARDING;
  905.             break;
  906.         case DISCARDING:
  907.             /* We are in the process of discarding an integer array. */
  908.             goagain = TRUE;
  909.             if (!(--(vp->count))) state[vw] = DONE;
  910.             else if (vp->count == 1)
  911.             {
  912.                 state[vw] = INTEGER;
  913.                 savstate[vw] = DONE;
  914.             }
  915.             else
  916.             {
  917.                 state[vw] = INTEGER;
  918.                 savstate[vw] = DISCARDING;
  919.             }
  920.             break;
  921.         case INTEGER:
  922.             if (c & 0x40)
  923.             {
  924.                 vp->intin = c & 0x3f;
  925.                 state[vw] = INTEGER1;
  926.             }
  927.             else
  928.             {
  929.                 vp->intin = c & 0x0f;
  930.                 if (!(c & 0x10)) vp->intin *= -1;
  931.                 state[vw] = savstate[vw];
  932.             }
  933.             break;
  934.         case INTEGER1:
  935.             if (c & 0x40)
  936.             {
  937.                 vp->intin = (vp->intin << 6) | (c & 0x3f);
  938.                 state[vw] = INTEGER2;
  939.             }
  940.             else
  941.             {
  942.                 vp->intin = (vp->intin << 4) | (c & 0x0f);
  943.                 if (!(c & 0x10)) vp->intin *= -1;
  944.                 state[vw] = savstate[vw];
  945.             }
  946.             break;
  947.         case INTEGER2:
  948.             vp->intin = (vp->intin << 4) | (c & 0x0f);
  949.             if (!(c & 0x10)) vp->intin *= -1;
  950.             state[vw] = savstate[vw];
  951.             break;
  952.         case IGNORE:            /* ignore next char; it's not supported */
  953.             state[vw] = DONE;
  954.             break;
  955.         case IGNORE2:            /* ignore next 2 chars */
  956.             state[vw] = IGNORE;
  957.             break;
  958.         case SOMEL:                /* now process 2nd letter */
  959.             switch(c)
  960.             {
  961.             case 'E':                    /* END PANEL 25jul90dsw */
  962.                 if (vp->TEKtype)
  963.                 {
  964.                     if (vp->TEKPanel)
  965.                     {
  966.                         if ((vp->current->x != vp->savx) ||
  967.                             (vp->current->y != vp->savy))
  968.                         {
  969.                             temppoint = (pointlist) myNewPtr(sizeof(point));
  970.                             temppoint->x = vp->savx;
  971.                             temppoint->y = vp->savy;
  972.                             temppoint->next = (pointlist) NULL;
  973.                             vp->current->next = temppoint;
  974.                         }
  975.                         temppoint = vp->current = vp->TEKPanel;
  976.                         vp->savx = vp->curx = vp->current->x;
  977.                         vp->savy = vp->cury = vp->current->y;
  978.                         vp->current = vp->current->next;
  979.                         DisposPtr((Ptr) temppoint);
  980.                         PanelRgn = NewRgn();
  981.                         OpenRgn();
  982.                         while (vp->current)
  983.                         {
  984.                             clipvec(vw,vp->curx,vp->cury,
  985.                                     vp->current->x,vp->current->y);
  986.                             temppoint = vp->current;
  987.                             vp->curx = vp->current->x;
  988.                             vp->cury = vp->current->y;
  989.                             vp->current = vp->current->next;
  990.                             DisposPtr((Ptr) temppoint);
  991.                         }
  992.                         CloseRgn(PanelRgn);
  993.                         if (vp->TEKPattern <= 0)
  994.                             (*RG[vp->RGdevice].pencolor)(vp->RGnum,-vp->TEKPattern);
  995.                         PaintRgn(PanelRgn);
  996.                 /*        if (vp->TEKOutline) 
  997.                             FrameRgn(PanelRgn); */
  998.                         DisposeRgn(PanelRgn);
  999.                         (*RG[vp->RGdevice].pencolor)(vp->RGnum,vp->pencolor);
  1000.                         vp->TEKPanel = (pointlist) NULL;
  1001.                         vp->curx = vp->savx;
  1002.                         vp->cury = vp->savy;
  1003.                     }
  1004.                 }
  1005.                 state[vw] = DONE;
  1006.                 break;
  1007.             case 'F':                    /* MOVE */
  1008.                 vp->modesave = vp->mode;
  1009.                 vp->mode = TEMPMOVE;
  1010.                 state[vw] = HIY;
  1011.                 break;
  1012.             case 'G':                    /* DRAW */
  1013.                 vp->modesave = vp->mode;
  1014.                 vp->mode = TEMPDRAW;
  1015.                 state[vw] = HIY;
  1016.                 break;
  1017.             case 'H':                    /* MARKER */
  1018.                 vp->modesave = vp->mode;
  1019.                 vp->mode = TEMPMARK;
  1020.                 state[vw] = HIY;
  1021.                 break;
  1022.             case 'I':                    /* DAINDEX 24jul90dsw*/
  1023.                 state[vw] = STARTDISC;
  1024.                 vp->intin = 3;
  1025.                 break;
  1026.             case 'L':
  1027.                 state[vw] = INTEGER;
  1028.                 savstate[vw] = DONE;
  1029.                 break;
  1030.             case 'P':                    /* BEGIN PANEL 17jul90dsw */
  1031.                 if (vp->TEKtype)        /* 4105 only */
  1032.                 {
  1033.                     state[vw] = HIY;
  1034.                     vp->mode = PANEL;
  1035.                 }
  1036.                 else
  1037.                     state[vw] = DONE;
  1038.                 break;
  1039.             case 'T':                    /* GTEXT 17jul90dsw */
  1040.                 if (vp->TEKtype)        /* 4105 only */
  1041.                 {
  1042.                     savstate[vw] = GTEXT;
  1043.                     state[vw] = INTEGER;
  1044.                 }
  1045.                 else
  1046.                     state[vw] = DONE;
  1047.                 break;
  1048.             default:
  1049.                 state[vw] = DONE;
  1050.             }
  1051.             break;
  1052.         case SOMEM:
  1053.             switch(c)
  1054.             {
  1055.             case 'C':                    /* set graphtext size */
  1056.                 savstate[vw] = GTSIZE0;
  1057.                 state[vw] = INTEGER;
  1058.                 break;
  1059.             case 'L':                    /* set line index */
  1060.                 savstate[vw] = COLORINT;
  1061.                 state[vw] = INTEGER;
  1062.                 break;
  1063.             case 'M':                    /* MARKERTYPE 17jul90dsw */
  1064.                 if (vp->TEKtype)
  1065.                 {
  1066.                     savstate[vw] = MARKER;
  1067.                     state[vw] = INTEGER;
  1068.                 }
  1069.                 else
  1070.                     state[vw] = DONE;
  1071.                 break;
  1072.             case 'N':                    /* GTPATH 17jul90dsw */
  1073.                 if (vp->TEKtype)
  1074.                 {
  1075.                     savstate[vw] = GTPATH;
  1076.                     state[vw] = INTEGER;
  1077.                 }
  1078.                 else
  1079.                     state[vw] = DONE;
  1080.                 break;
  1081.             case 'P':                    /* FillPattern 17jul90dsw */
  1082.                 if (vp->TEKtype)
  1083.                 {
  1084.                     savstate[vw] = FPATTERN;
  1085.                     state[vw] = INTEGER;
  1086.                 }
  1087.                 else
  1088.                     state[vw] = DONE;
  1089.                 break;
  1090.             case 'R':                    /* GTROT 17jul90dsw */
  1091.                 if (vp->TEKtype)
  1092.                 {
  1093.                     savstate[vw] = GTROT;
  1094.                     state[vw] = INTEGER;
  1095.                 }
  1096.                 else
  1097.                     state[vw] = DONE;
  1098.                 break;
  1099.             case 'T':                    /* GTINDEX 17jul90dsw */
  1100.                 if (vp->TEKtype)
  1101.                 {
  1102.                     savstate[vw] = GTINDEX;
  1103.                     state[vw] = INTEGER;
  1104.                 }
  1105.                 else
  1106.                     state[vw] = DONE;
  1107.                 break;
  1108.             case 'V':
  1109.                 if (vp->TEKtype)
  1110.                 {
  1111.                     state[vw] = INTEGER;
  1112.                     savstate[vw] = DONE;
  1113.                 }
  1114.                 else
  1115.                     state[vw] = DONE;
  1116.                 break;
  1117.             default:
  1118.                 state[vw] = DONE;
  1119.             }
  1120.             break;
  1121.         case COLORINT:                /* set line index; have integer */
  1122.             vp->pencolor = vp->intin;
  1123.             (*RG[vp->RGdevice].pencolor)(vp->RGnum,vp->intin);
  1124.             state[vw] = CANCEL;
  1125.             goagain = TRUE;            /* we ignored current char; now process it */
  1126.             break;
  1127.         case GTSIZE0:                /* discard the first integer; get the 2nd */
  1128.             state[vw] = INTEGER;    /* get the important middle integer */
  1129.             savstate[vw] = GTSIZE1;
  1130.             goagain = TRUE;
  1131.             break;
  1132.         case GTSIZE1:                /* integer is the height */
  1133.             if (vp->TEKtype)
  1134.             {
  1135.                 if (vp->intin < 88) vp->TEKSize = 1;
  1136.                 else if ((vp->intin > 87) && (vp->intin < 149)) vp->TEKSize = 2;
  1137.                 else if ((vp->intin > 148) && (vp->intin < 209)) vp->TEKSize = 3;
  1138.                 else if (vp->intin > 208) vp->TEKSize = vp->intin / 61;
  1139.                 VGwin[vw]->charx = (vp->TEKSize * 52);
  1140.                 VGwin[vw]->chary = (vp->TEKSize * 64);
  1141.             }
  1142.             else
  1143.             {
  1144.                 if (vp->intin < 88)
  1145.                     fontnum(vw,0);
  1146.                 else if (vp->intin < 149)
  1147.                     fontnum(vw,4);
  1148.                 else
  1149.                     fontnum(vw,5);
  1150.             }
  1151.             state[vw] = INTEGER;    /* discard last integer */
  1152.             savstate[vw] = DONE;
  1153.             goagain = TRUE;
  1154.             break;
  1155.         case GTEXT:                    /* TEK4105 GraphText output.  17jul90dsw */
  1156.             if (vp->intin > 0)
  1157.             {
  1158.                 drawc(vw,(short) c);    /* Draw the character */
  1159.                 vp->intin--;        /* One less character in the string... */
  1160.             }
  1161.             else
  1162.             {
  1163.                 goagain = TRUE;
  1164.                 state[vw] = DONE;
  1165.                 newcoord(vw);
  1166.             }
  1167.             break;
  1168.         case MARKER:                /* TEK4105 Set marker type.  17jul90dsw */
  1169.             vp->TEKMarker = vp->intin;
  1170.             if (vp->TEKMarker > 10) vp->TEKMarker = 10;
  1171.             if (vp->TEKMarker <  0) vp->TEKMarker = 0;
  1172.             state[vw] = DONE;
  1173.             goagain = TRUE;
  1174.             break;
  1175.         case GTPATH:
  1176.             vp->TEKPath = vp->intin;
  1177.             state[vw] = DONE;
  1178.             goagain = TRUE;
  1179.             break;
  1180.         case FPATTERN:
  1181.             vp->TEKPattern = (vp->intin <  -7) ?  -7 :
  1182.                              (vp->intin > 149) ? 149 : vp->intin;
  1183.             state[vw] = DONE;
  1184.             goagain = TRUE;
  1185.             break;
  1186.         case GTROT:
  1187.             vp->TEKRot = vp->intin;
  1188.             state[vw] = INTEGER;
  1189.             savstate[vw] = GTROT1;
  1190.             goagain = TRUE;
  1191.             break;
  1192.         case GTROT1:
  1193.             vp->TEKRot = (vp->TEKRot) << (vp->intin);
  1194.             vp->TEKRot = ((vp->TEKRot + 45) / 90) * 90;
  1195.             state[vw] = DONE;
  1196.             goagain = TRUE;
  1197.             break;
  1198.         case GTINDEX:
  1199.             vp->TEKIndex = (vp->intin < 0) ? 0 : (vp->intin > 7) ? 7 : vp->intin;
  1200.             state[vw] = DONE;
  1201.             goagain = TRUE;
  1202.             break;
  1203.         case PANEL:
  1204.             vp->TEKOutline = (vp->intin == 0) ? 0 : 1;
  1205.             temppoint = (pointlist) myNewPtr(sizeof(point));
  1206.             if (vp->TEKPanel)
  1207.             {
  1208.                 if ((vp->current->x != vp->savx) && (vp->current->y != vp->savy))
  1209.                 {
  1210.                     temppoint->x = vp->savx;
  1211.                     temppoint->y = vp->savy;
  1212.                     vp->current->next = temppoint;
  1213.                     vp->current = temppoint;
  1214.                     temppoint = (pointlist) myNewPtr(sizeof(point));
  1215.                 }
  1216.                 vp->current->next = temppoint;
  1217.             }
  1218.             else vp->TEKPanel = temppoint;
  1219.             vp->current = temppoint;
  1220.             vp->current->x = vp->savx = joinup(vp->nhix,vp->nlox,vp->nex);
  1221.             vp->current->y = vp->savy = joinup(vp->nhiy,vp->nloy,vp->ney);
  1222.             vp->current->next = (pointlist) NULL;
  1223.             state[vw] = INTEGER;
  1224.             savstate[vw] = PANEL;
  1225.             vp->mode = DONE;
  1226.             newcoord(vw);
  1227.             state[vw] = DONE;
  1228.             goagain = TRUE;
  1229.             break;
  1230.         case DONE:                    /* ready for anything */
  1231.             switch(c)
  1232.             {
  1233.             case 31:                /* US - enter ALPHA mode */
  1234.                 vp->mode = ALPHA; 
  1235.                 state[vw] = CANCEL;
  1236.                 break;
  1237.             case 30:
  1238.                 state[vw] = RS;
  1239.                 break;
  1240.             case 28:
  1241.                     vp->mode = MARK;
  1242.                     state[vw] = HIY;
  1243.                 break;
  1244.             case 29:                /* GS - enter VECTOR mode */
  1245.                 state[vw] = ENTERVEC;
  1246.                 break;
  1247.             case 27:
  1248.                 state[vw] = CMD0;
  1249.                 break;
  1250.             default:
  1251.                 if (vp->mode == ALPHA)
  1252.                 {
  1253.                     state[vw] = DONE;
  1254.                     if (! vp->TEKtype)
  1255.                         drawc(vw,(short) c);
  1256.                     else
  1257.                     {
  1258.                         VSwrite(vp->theVS,&c,1);
  1259.                         TEKunstore(VGstore[vw]);
  1260.                     }
  1261.                     return;
  1262.                 }
  1263.                 else if ((vp->mode == DRAW) && cmd)
  1264.                 {
  1265.                     state[vw] = HIY;
  1266.                     goagain = TRUE;
  1267.                 }
  1268.                 else if ((vp->mode == MARK) && cmd)
  1269.                 {
  1270.                     state[vw] = HIY;
  1271.                     goagain = TRUE;
  1272.                 }
  1273.                 else if ((vp->mode == DRAW) && ((c == 13) || (c == 10)))
  1274.                 {
  1275.                     /* break drawing mode on CRLF */
  1276.                     vp->mode = ALPHA; 
  1277.                     state[vw] = CANCEL;
  1278.                 }
  1279.                 else
  1280.                 {
  1281.                     state[vw] = DONE;            /* do nothing */
  1282.                     return;
  1283.                 }
  1284.             }
  1285.         }
  1286.     
  1287.         if (state[vw] == DONE)
  1288.         {
  1289.             if (vp->mode == PANEL)
  1290.             {
  1291.                 vp->mode = DONE;
  1292.                 state[vw] = INTEGER;
  1293.                 savstate[vw] = PANEL;
  1294.             }
  1295.             else if ((vp->TEKPanel) && ((vp->mode == DRAW) || (vp->mode == TEMPDRAW)
  1296.                     || (vp->mode == MARK) || (vp->mode == TEMPMARK) ||
  1297.                         (vp->mode == TEMPMOVE)))
  1298.             {
  1299.                 temppoint = (pointlist) myNewPtr(sizeof(point));
  1300.                 vp->current->next = temppoint;
  1301.                 vp->current = temppoint;
  1302.                 vp->current->x = joinup(vp->nhix,vp->nlox,vp->nex);
  1303.                 vp->current->y = joinup(vp->nhiy,vp->nloy,vp->ney);
  1304.                 vp->current->next = (pointlist) NULL;
  1305.                 if ((vp->mode == TEMPDRAW) || (vp->mode == TEMPMOVE) ||
  1306.                     (vp->mode == TEMPMARK))
  1307.                     vp->mode = vp->modesave;
  1308.                 newcoord(vw);
  1309.             }
  1310.             else if (vp->mode == TEMPMOVE)
  1311.             {
  1312.                 vp->mode = vp->modesave;
  1313.                 newcoord(vw);
  1314.             }
  1315.             else if ((vp->mode == DRAW) || (vp->mode == TEMPDRAW))
  1316.             {
  1317.                 clipvec(vw,vp->curx,vp->cury,
  1318.                     joinup(vp->nhix,vp->nlox,vp->nex),
  1319.                     joinup(vp->nhiy,vp->nloy,vp->ney));
  1320.                 newcoord(vw);
  1321.                 if (vp->mode == TEMPDRAW) vp->mode = vp->modesave;
  1322.             }
  1323.             else if ((vp->mode == MARK) || (vp->mode == TEMPMARK))
  1324.             {
  1325.                 newcoord(vw);
  1326.                 if (vp->TEKtype) drawc(vw,127 + vp->TEKMarker);
  1327.                 newcoord(vw);
  1328.                 if (vp->mode == TEMPMARK) vp->mode = vp->modesave;
  1329.             }
  1330.         }
  1331.  
  1332.         if (state[vw] == CANCEL) state[vw] = DONE;
  1333.     } while (goagain);
  1334.     return;
  1335. }
  1336.  
  1337. /*  Clear screen and have a few other effects:
  1338.  *    - Return graphics to home position (0,3071)
  1339.  *    - Switch to alpha mode
  1340.  *    This is a standard Tek command; don't look at me.
  1341.  */
  1342. void VGpage(short vw)
  1343. {
  1344.     if (VGcheck(vw)) {
  1345.         return;
  1346.         }
  1347.  
  1348.     if (VGwin[vw]->TEKtype)
  1349.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->TEKBackground);
  1350.     else
  1351.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,0);
  1352.     (*RG[VGwin[vw]->RGdevice].clrscr)(VGwin[vw]->RGnum);
  1353.     (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,1);
  1354.     VGwin[vw]->mode = ALPHA;
  1355.     state[vw] = DONE;
  1356.     VGwin[vw]->textcol = 0;
  1357.     fontnum(vw,0);
  1358.     storexy(vw,0,3071);
  1359. }
  1360.  
  1361. /*    Redraw window 'vw' in pieces to window 'dest'.
  1362.  *    Must call this function repeatedly to draw whole image.
  1363.  *    Only draws part of the image at a time, to yield CPU power.
  1364.  *    Returns 0 if needs to be called more, or 1 if the image
  1365.  *    is complete.  Another call would result in the redraw beginning again.
  1366.  *    User should clear screen before beginning redraw.
  1367.  */
  1368. short VGpred(short vw, short dest)
  1369. {
  1370.     short        data;
  1371.     TEKSTOREP    st;
  1372.     short        count = 0;
  1373.     
  1374.     if (VGcheck(vw)) {
  1375.         return -1;
  1376.         }
  1377.  
  1378.     st = VGstore[vw];
  1379.     
  1380.     if (drawing[vw])        /* wasn't redrawing */
  1381.     {
  1382.         topTEKstore(VGstore[vw]);
  1383.         drawing[vw] = 0;    /* redraw incomplete */
  1384.     }
  1385.  
  1386.     while (++count < PREDCOUNT && ((data = nextTEKitem(st)) != -1))
  1387.         VGdraw(dest,data);
  1388.  
  1389.     if (data == -1) drawing[vw] = 1;     /* redraw complete */
  1390.     return(drawing[vw]);
  1391. }
  1392.  
  1393. /*    Abort VGpred redrawing of specified window.
  1394.     Must call this routine if you decide not to complete the redraw. */
  1395. void VGstopred(short vw)
  1396. {
  1397.     if (VGcheck(vw)) {
  1398.         return;
  1399.         }
  1400.  
  1401.     drawing[vw] = 1;
  1402. }
  1403.  
  1404. /*    Redraw the contents of window 'vw' to window 'dest'.
  1405.  *    Does not yield CPU until done.
  1406.  *    User should clear the screen before calling this, to avoid 
  1407.  *    a messy display. */
  1408. void VGredraw(short vw, short dest)
  1409. {
  1410.     short    data;
  1411.  
  1412.     if (VGcheck(vw)) {
  1413.         return;
  1414.         }
  1415.  
  1416.     topTEKstore(VGstore[vw]);
  1417.     while ((data = nextTEKitem(VGstore[vw])) != -1) VGdraw(dest,data);
  1418. }
  1419.  
  1420. /*    Send interesting information about the virtual window down to
  1421.  *    its RG, so that the RG can make VG calls and display zoom values
  1422.  */
  1423. void    VGgiveinfo(short vw)
  1424. {
  1425.     if (VGcheck(vw)) {
  1426.         return;
  1427.         }
  1428.  
  1429.     (*RG[VGwin[vw]->RGdevice].info)(VGwin[vw]->RGnum,
  1430.         vw,
  1431.         VGwin[vw]->winbot,
  1432.         VGwin[vw]->winleft,
  1433.         VGwin[vw]->wintop,
  1434.         VGwin[vw]->winright);
  1435. }
  1436.  
  1437. /*    Set new borders for zoom/pan region.
  1438.  *    x0,y0 is lower left; x1,y1 is upper right.
  1439.  *    User should redraw after calling this.
  1440.  */
  1441. void    VGzoom(short vw, short x0, short y0, short x1, short y1)
  1442. {
  1443.     if (VGcheck(vw)) {
  1444.         return;
  1445.         }
  1446.  
  1447.     VGwin[vw]->winbot = y0;
  1448.     VGwin[vw]->winleft = x0;
  1449.     VGwin[vw]->wintop = y1;
  1450.     VGwin[vw]->winright = x1;
  1451.     VGwin[vw]->wintall = y1 - y0 + 1;
  1452.     VGwin[vw]->winwide = x1 - x0 + 1;
  1453.     VGgiveinfo(vw);
  1454. }
  1455.  
  1456. void    VGwhatzoom(short vw, short *px0, short *py0, short *px1, short *py1)
  1457. {
  1458.     if (VGcheck(vw)) {
  1459.         return;
  1460.         }
  1461.  
  1462.     *py0 = VGwin[vw]->winbot;
  1463.     *px0 = VGwin[vw]->winleft;
  1464.     *py1 = VGwin[vw]->wintop;
  1465.     *px1 = VGwin[vw]->winright;
  1466. }
  1467.  
  1468. /*    Set zoom/pan borders for window 'dest' equal to those for window 'src'.
  1469.  *    User should redraw window 'dest' after calling this.
  1470.  */
  1471. void    VGzcpy(short src, short dest)
  1472. {
  1473.     VGzoom(dest,VGwin[src]->winleft, VGwin[src]->winbot,
  1474.     VGwin[src]->winright, VGwin[src]->wintop);
  1475. }
  1476.  
  1477. /*    Close virtual window.
  1478. /*    Draw the data pointed to by 'data' of length 'count'
  1479.  *    on window vw, and add it to the store for that window.
  1480.  *    This is THE way for user program to pass Tektronix data.
  1481.  */
  1482. short    VGwrite(short vw, char *data, short count)
  1483. {
  1484.     char *c = data;
  1485.     char *end = &(data[count]);
  1486.     char storeit;
  1487.  
  1488.     if (VGcheck(vw)) {
  1489.         return -1;
  1490.         }
  1491.  
  1492.     storeit = storing[vw];
  1493.     
  1494.     while (c != end)
  1495.     {
  1496.         if (*c == 24)                /* ASC CAN character */
  1497.             return(c-data+1);
  1498.         if (storeit) addTEKstore(VGstore[vw],*c);
  1499.         VGdraw(vw,*c++);
  1500.  
  1501.     }
  1502.     return(count);
  1503. }
  1504.  
  1505. /*    Return a pointer to a human-readable string
  1506.  *    which describes the specified real device
  1507.  */
  1508. char *    VGrgname(short rgdev)
  1509. {
  1510.     return(*RG[rgdev].devname)();
  1511. }
  1512.  
  1513. /*    Put the specified real device into text mode */
  1514. void    VGtmode(short rgdev)
  1515. {
  1516.     (*RG[rgdev].tmode)();
  1517. }
  1518.  
  1519. /*    Translate data for output as GIN report.
  1520.  *
  1521.  *    User indicates VW number and x,y coordinates of the GIN cursor.
  1522.  *    Coordinate space is 0-4095, 0-4095 with 0,0 at the bottom left of
  1523.  *    the real window and 4095,4095 at the upper right of the real window.
  1524.  *    'c' is the character to be returned as the keypress.
  1525.  *    'a' is a pointer to an array of 5 characters.  The 5 chars must
  1526.  *    be transmitted by the user to the remote host as the GIN report. */
  1527. void VGgindata( short vw,
  1528.     unsigned short x,        /* NCSA: SB - UNSIGNED data */
  1529.     unsigned short y,        /* NCSA: SB - "          "  */
  1530.     char c, char *a)
  1531. {
  1532.     long    x2,y2;
  1533.     
  1534.     if (VGcheck(vw)) {
  1535.         return;
  1536.         }
  1537.  
  1538.     x2 = ((x * VGwin[vw]->winwide) / INXMAX + VGwin[vw]->winleft) >> 2;
  1539.     y2 = ((y * VGwin[vw]->wintall) / INYMAX + VGwin[vw]->winbot) >> 2;
  1540.  
  1541.     a[0] = c;
  1542.     a[1] = 0x20 | ((x2 & 0x03E0) >> 5);
  1543.     a[2] = 0x20 | (x2 & 0x001F);
  1544.     a[3] = 0x20 | ((y2 & 0x03E0) >> 5);
  1545.     a[4] = 0x20 | (y2 & 0x001F);
  1546. }
  1547.